Much expanded overview docs for GtkTreeView and related objects.
authorCody Russell <bratsche@src.gnome.org>
Thu, 21 Mar 2002 04:48:31 +0000 (04:48 +0000)
committerCody Russell <bratsche@src.gnome.org>
Thu, 21 Mar 2002 04:48:31 +0000 (04:48 +0000)
docs/reference/ChangeLog
docs/reference/gtk/tree_widget.sgml

index 45e2739508d746958a41ea8c678c3c78883f59e7..7b0148e9574bcabcd14301fe36d11483da8a17df 100644 (file)
@@ -1,3 +1,7 @@
+2002-03-20  Cody Russell  <cody@jhu.edu>
+
+       * gtk/tree_widget.sgml: Much expanded overview of the tree.
+
 Tue Mar 12 00:29:31 2002  Jonathan Blandford  <jrb@redhat.com>
 
        * gtk/question_index.sgml: new FAQ.
index 95619b1a1057bed524a9cfe3f0cd33ca7247f74c..f95525019f31d2a4e297d89088e042c61a2e30fa 100644 (file)
@@ -1,4 +1,4 @@
-<refentry id="TreeWidget" revision="30 Oct 2000">
+<refentry id="TreeWidget" revision="20 Mar 2002">
   <refmeta>
     <refentrytitle>Tree and List Widget Overview</refentrytitle>
     <manvolnum>3</manvolnum>
        created to display various parts of the file system, but only one
        copy need be kept in memory.
     </para>
+    <para>
+        The purpose of the cell renderers is to provide extensibility to the
+        widget and to allow multiple ways of rendering the same type of data.
+        For example, consider how to render a boolean variable.  Should you
+        render it as a string of "True" or "False", "On" or "Off", or should
+        you render it as a checkbox?
+    </para>
   </refsect1>
+  <refsect1>
+    <title>Creating a model</title>
+    <para>
+      GTK+ 2.0 provides two types of models that can be used:
+      <link linkend="GtkListStore">GtkListStore</link> and
+      <link linkend="GtkTreeStore">GtkTreeStore</link>.  GtkListStore is
+      used to model columned list widgets, while GtkTreeStore models
+      columned tree widgets.  It is possible to develop a new type of model,
+      but the existing models should be satisfactory for all but the most
+      specialized of situations.  Creating the model is quite simple:
+    </para>
+      <informalexample><programlisting><![CDATA[
+GtkListStore *store = gtk_list_store_new (2, G_TYPE_STRING, G_TYPE_BOOLEAN);
+]]></programlisting></informalexample>
+    <para>
+      This creates a list store with two columns: a string column and a boolean
+      column.  Typically the 2 is never passed directly like that; usually an
+      enum is created wherein the different columns are enumerated, followed by
+      a token that represents the total number of columns.  The next example will
+      illustrate this, only using a tree store instead of a list store. Creating
+      a tree store operates almost exactly the same.
+    </para>
+    <informalexample><programlisting><![CDATA[
+enum
+{
+   TITLE_COLUMN,
+   AUTHOR_COLUMN,
+   CHECKED_COLUMN,
+   N_COLUMNS
+};
+
+GtkTreeStore *store = gtk_tree_store_new (N_COLUMNS,       /* Total number of columns */
+                                          G_TYPE_STRING,   /* Book title              */
+                                          G_TYPE_STRING,   /* Author                  */
+                                          G_TYPE_BOOLEAN); /* Is checked out?         */
+]]></programlisting</informalexample>
+    <para>
+      Adding data to the model is done using <link linkend="gtk_tree_store_set">
+      gtk_tree_store_set()</link> or <link linkend="gtk_list_store_set">
+      gtk_list_store_set()</link>, depending upon which sort of model was
+      created.  To do this, a <link linkend="GtkTreeIter">GtkTreeIter</link> must
+      be acquired.  The iterator points to the location where data will be added.
+    </para>
+    <para>
+      Once an iterator has been acquired, <link linkend="gtk_tree_store_set">
+      gtk_tree_store_set()</link> is used to apply data to the part of the model
+      that the iterator points to.  Consider the following example:
+    </para>
+    <informalexample><programlisting><![CDATA[
+GtkTreeIter   iter;
+
+gtk_tree_store_append (store, &iter, NULL);  /* Acquire an iterator */
+
+gtk_tree_store_set (store, &iter,
+                    TITLE_COLUMN, "The Principle of Reason",
+                    AUTHOR_COLUMN, "Martin Heidegger",
+                    CHECKED_COLUMN, FALSE);
+]]></programlisting></informalexample>
+
+  <para>
+    Notice that the last argument is FALSE.  This is always done because
+    this is a variable-argument function and it needs to know when to stop
+    processing arguments.  It can be used to set the data in any or all
+    columns in a given row.
+  </para>
+  <para>
+    The third argument to gtk_tree_store_append() is the parent iterator.  It
+    is used to add a row to a GtkTreeStore as a child of an existing row.  This
+    means that the new row will only be visible when its parent is visible and
+    in its expanded state.  Consider the following example:
+  </para>
+  <informalexample><programlisting><![CDATA[
+GtkTreeIter iter1;  /* Parent iter */
+GtkTreeIter iter2;  /* Child iter  */
+
+gtk_tree_store_append (store, &iter1, NULL);  /* Acquire a top-level iterator */
+gtk_tree_store_set (store, &iter1,
+                    TITLE_COLUMN, "The Art of Computer Programming",
+                    AUTHOR_COLUMN, "Donald E. Knuth",
+                    CHECKED_COLUMN, FALSE,
+                    NULL);
+
+gtk_tree_store_append (store, &iter2, &iter1);  /* Acquire a child iterator */
+gtk_tree_store_set (store, &iter2,
+                    TITLE_COLUMN, "Volume 1: Fundamental Algorithms",
+                    NULL);
+
+gtk_tree_store_append (store, &iter2, &iter1);
+gtk_tree_store_set (store, &iter2,
+                    TITLE_COLUMN, "Volume 2: Seminumerical Algorithms",
+                    NULL);
+
+gtk_tree_store_append (store, &iter2, &iter1);
+gtk_tree_store_set (store, &iter2,
+                    TITLE_COLUMN, "Volume 3: Sorting and Searching",
+                    NULL);
+]]></programlisting></informalexample>
+  </refsect1>
+
+  <refsect1>
+    <title>Creating the view component</title>
+    <para>
+      While there are two different models to choose from, there is only one
+      view widget to deal with.  It works with either the list or the tree store.
+      Setting up a <link linkend="GtkTreeView">GtkTreeView</link> is not a
+      difficult matter.  It needs a <link linkend="GtkTreeModel">GtkTreeModel</link>
+      to know where to retrieve its data from.
+    </para>
+    <informalexample><programlisting><![CDATA[
+GtkWidget *tree;
+
+tree = gtk_tree_view_new_with_model (GTK_TREE_MODEL (store));
+]]></programlisting></informalexample>
+
+    <refsect2>
+      <title>Columns and cell renderers</title>
+      <para>
+        Cell renderers are used to draw the data in the tree model in a certain way.
+        There are three cell renderers to choose from with GTK+ 2.0, but the
+        adventuresome hacker may write more.
+      </para>
+      <informalexample><programlisting><![CDATA[
+GtkCellRenderer *renderer;
+GtkTreeViewColumn *column;
+
+renderer = gtk_cell_renderer_text_new ();
+column = gtk_tree_view_column_new_with_attributes ("Author",
+                                                   renderer,
+                                                   "text", AUTHOR_COLUMN,
+                                                   NULL);
+gtk_tree_view_append_column (GTK_TREE_VIEW (tree), column);
+]]></programlisting></informalexample>
+      <para>
+        A <link linkend="GtkTreeViewColumn">GtkTreeViewColumn</link> is the
+        object that GtkTreeView uses to organize the vertical columns in
+        the tree view.  It needs to know the name of the column to label
+        for the user, what type of cell renderer to use, and which piece of
+        data to retrieve from the model for a given row.
+      </para>
+      <para>
+       At this point, all the steps in creating a displayable tree have been
+       covered.  The model is created, data is stored in it, a tree view is
+       created and columns are added to it.
+      </para>
+    </refsect2>
+
+    <refsect2>
+      <title>Selection handling</title>
+      <para>
+        Most applications will need to not only deal with displaying data, but also
+        receiving input events from users.  To do this, simply get a reference to
+        a selection object and connect to the "changed" signal.
+      </para>
+      <informalexample><programlisting><![CDATA[
+/* Prototype for selection handler callback */
+static void tree_selection_changed_cb (GtkTreeSelection *selection, gpointer data);
+
+/* Setup the selection handler */
+GtkTreeSelection *select;
+
+select = gtk_tree_view_get_selection (GTK_TREE_VIEW (tree));
+gtk_tree_selection_set_mode (select, GTK_SELECT_SINGLE);
+g_signal_connect (G_OBJECT (select), "changed",
+                  G_CALLBACK (tree_selection_changed_cb),
+                  NULL);
+]]></programlisting></informalexample>
+        <para>
+          Then to retrieve data for the row selected:
+        </para>
+        <informalexample><programlisting><![CDATA[
+static void
+tree_selection_changed_cb (GtkTreeSelection *selection, gpointer data)
+{
+        GtkTreeIter iter;
+        GtkTreeModel *model;
+        gchar *author;
+
+        if (gtk_tree_selection_get_selected (selection, &model, &iter))
+        {
+                gtk_tree_model_get (model, &iter, AUTHOR_COLUMN, &author, -1);
+
+                g_print ("You selected a book by %s\n", author);
+
+                g_free (author);
+        }
+}
+]]></programlisting></informalexample>
+    </refsect2>
+  </refsect1>
+
   <refsect1>
     <title>Simple Example</title>
     <para>
       <informalexample><programlisting><![CDATA[
 enum
 {
-  COLUMN_ONE,
-  N_COLUMNS
+   TITLE_COLUMN,
+   AUTHOR_COLUMN,
+   CHECKED_COLUMN,
+   N_COLUMNS
 };
 
+void
+setup_tree (void)
 {
-  GtkTreeStore *model;
-  GtkWidget *view;
-  GtkTreeViewColumn *column;
-  GtkCellRenderer *cell_renderer;
-
-  /* Create a model.  We are using the store model for now, though we
-   * could use any other GtkTreeModel */
-  model = gtk_tree_store_new (N_COLUMNS, G_TYPE_STRING);
-
-  /* custom function to fill the model with data */
-  populate_tree_model (model);
-
-  /* Create a view */
-  view = gtk_tree_view_new_with_model (GTK_TREE_MODEL (model));
-
-  /* The view now holds a reference.  We can get rid of our own
-   * reference */
-  g_object_unref (G_OBJECT (model));
-
-  /* Create a cell render and arbitrarily make it red for demonstration
-   * purposes */
-  cell_renderer = gtk_cell_renderer_text_new ();
-  g_object_set (G_OBJECT (cell_renderer), "foreground", "red", NULL);
-
-  /* Create a column, associating the "text" attribute of the
-   * cell_renderer to the first column of the model */
-  column = gtk_tree_view_column_new_with_attributes ("title",
-                                                    cell_renderer,
-                                                    "text", COLUMN_ONE,
-                                                    NULL);
-
-  /* Add the column to the view. */
-  gtk_tree_view_append_column (GTK_TREE_VIEW (view), column);
-
-  /* Now we can manipulate the view just like any other GTK widget */
-  ...
+   GtkTreeStore *store;
+   GtkWidget *tree;
+   GtkTreeViewColumn *column;
+   GtkCellRenderer *renderer;
+
+   /* Create a model.  We are using the store model for now, though we
+    * could use any other GtkTreeModel */
+   store = gtk_tree_store_new (N_COLUMNS,
+                               G_TYPE_STRING,
+                               G_TYPE_STRING,
+                               G_TYPE_BOOLEAN);
+
+   /* custom function to fill the model with data */
+   populate_tree_model (store);
+
+   /* Create a view */
+   view = gtk_tree_view_new_with_model (GTK_TREE_MODEL (store));
+
+   /* The view now holds a reference.  We can get rid of our own
+    * reference */
+   g_object_unref (G_OBJECT (store));
+
+   /* Create a cell render and arbitrarily make it red for demonstration
+    * purposes */
+   renderer = gtk_cell_renderer_text_new ();
+   g_object_set (G_OBJECT (renderer), "foreground", "red", NULL);
+
+   /* Create a column, associating the "text" attribute of the
+    * cell_renderer to the first column of the model */
+   column = gtk_tree_view_column_new_with_attributes ("Author",
+                                                      renderer,
+                                                      "text", AUTHOR_COLUMN,
+                                                      NULL);
+
+   /* Add the column to the view. */
+   gtk_tree_view_append_column (GTK_TREE_VIEW (tree), column);
+
+   /* Second column.. title of the book. */
+   renderer = gtk_cell_renderer_text_new ();
+   column = gtk_tree_view_column_new_with_attributes ("Title",
+                                                      renderer,
+                                                      "text", TITLE_COLUMN,
+                                                      NULL);
+   gtk_tree_view_append_column (GTK_TREE_VIEW (tree), column);
+
+   /* Last column.. whether a book is checked out. */
+   renderer = gtk_cell_renderer_toggle_new ();
+   column = gtk_tree_view_column_new_with_attributes ("Checked out",
+                                                      renderer,
+                                                      "active", CHECKED_COLUMN,
+                                                      NULL);
+   gtk_tree_view_append_column (GTK_TREE_VIEW (tree), column);
+
+   /* Now we can manipulate the view just like any other GTK widget */
+   ...
 }
 ]]>
       </programlisting></informalexample>